package com.zzyang.aop.demo.interceptor;

import com.zzyang.aop.demo.interceptor.anno.AopInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


/**
 * aop
 *
 * @author zhuoziyang
 * @date 2021/5/16 22:56
 */
public class AopInterceptorInvocationHandler implements InvocationHandler {

    private final Object target;

    public AopInterceptorInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method targetMethod;
        if (args.length == 0) {
            targetMethod = target.getClass().getDeclaredMethod(method.getName());
        } else {
            Class[] classArray = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classArray[i] = args[i].getClass();
            }
            targetMethod = target.getClass().getDeclaredMethod(method.getName(), classArray);
        }

        AopInterceptor annotation = targetMethod.getAnnotation(AopInterceptor.class);
        if (annotation == null) {
            return targetMethod.invoke(target, args);
        }
        Class<? extends Interceptor> interceptorClass = annotation.interceptor();
        if (Interceptor.class.equals(interceptorClass)) {
            return targetMethod.invoke(target, args);
        }
        Interceptor interceptor = interceptorClass.newInstance();
        Invocation invocation = new Invocation();
        invocation.setProxy(proxy)
                .setTarget(target)
                .setMethod(targetMethod)
                .setArgs(args);
        interceptor.before(invocation);
        return interceptor.after(invocation);
    }
}
